from django.shortcuts import render
from users.models import *
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.viewsets import ModelViewSet
import re  # 正则模块
# 校验工具
from django.contrib.auth.hashers import check_password, make_password
import random  # 随即模块
from captcha.image import ImageCaptcha  # 生成图片验证码的模块
from captcha.audio import AudioCaptcha
import string  # 字符串
import redis  # redis数据库
from django.http import HttpResponse
from django.contrib.auth import authenticate
from django.db.models import Q
from rest_framework_jwt.utils import jwt_payload_handler, jwt_encode_handler

from users.serializer import UserSer, AddressSer


# Create your views here.
# 生成图片验证码
class ImageCode(APIView):
    def get(self, request, imageCodeID):
        """
        生成图片验证码
        1,接收前端传来的uuid,图片id
        2,使用随机模块生成,字符+数字的随机数,长度自定
        3,使用captcha模块生成图片
        4,返回生成的图片
        """
        # 使用随即模块生成:
        # 数字加字符的字符串
        # string.ascii_letters   生成区分大小写的字符
        # string.digits:生成0-9的随机数字
        salt = ''.join(random.sample(string.ascii_letters + string.digits, 6))
        # 生成图片验证码
        img = ImageCaptcha()
        # 把生成的随机数字添加到图片上
        image = img.generate(salt)

        # 连接redis数据库
        redis_conn = redis.Redis(host="localhost", port=6379, db=0)
        # 将图片验证码添加到redis数据库中
        # redis_conn.set(str(imageCodeID), salt, ex=600)
        redis_conn.setex(str(imageCodeID), 600, salt)
        # 返回图片
        return HttpResponse(image, content_type='image/png')


# 校验图片验证码
class CheckImageCode(APIView):
    def get(self, request):
        # 接收请求传递的数据
        uuid_ = request.query_params.get("imageCodeID")
        image_code_ = request.query_params.get("imageCode")
        # 根据前端传来的uuid取出redis中的图片验证码
        redis_conn = redis.Redis(host="localhost", port=6379, db=0)
        image_code = redis_conn.get(uuid_)
        if image_code:
            # 通过接收请求收到的数据 与  数据库中查到的数据对比
            # lower() 将字符串转换为小写
            # decode() 解码
            if image_code.decode().lower() == image_code_.lower():
                return Response({"msg": "OK", "code": 200})
            return Response({"msg": "验证码错误", "code": 204})
        # 数据为空 验证码过期
        return Response({"msg": "验证码已过期", "code": 404})


# 校验用户名
class CheckUsername(APIView):
    def get(self, request, username):
        # 判断用户名是否重复
        rest = Users.objects.filter(username=username).count()
        if rest > 0:
            # 说明用户名已存在
            return Response({"msg": "用户名已存在", "code": 400})
        return Response({'code': 200})


# 校验手机号
class CheckMobile(APIView):
    def get(self, request, mobile):
        # 判断手机号是否重复
        rest = Users.objects.filter(mobile=mobile).count()
        if rest > 0:
            # 说明手机号已存在
            return Response({"msg": "手机号已存在", "code": 400})
        return Response({'code': 200})


# 注册校验
class UserRegister(APIView):
    def post(self, request):
        # 注册业务逻辑
        user_name = request.data.get("userName")
        pwd = request.data.get("pwd")
        mobile = request.data.get("mobile")
        agree = request.data.get("agree")
        # 后端要校验前端传来的数据
        # 只要有一个为空就报错
        if not all([user_name, pwd, mobile, agree]):
            return Response({"msg": "请完善注册用户信息", "code": 400})
        if not agree:
            # 说明没有同意协议
            return Response({"msg": "请勾选协议"})
        # 写入数据库
        # create() 写入数据库时,密码是明文存储,不安全
        # create_user会把密码进行加密存储
        Users.objects.create_user(username=user_name, password=pwd, mobile=mobile, agree=agree)
        return Response({"msg": "注册成功", "code": 200})


# 登录校验
class UserLogin(APIView):
    def post(self, request):
        # 登录业务逻辑
        username = request.data.get("user")
        pwd = request.data.get("pwd")
        try:
            user = Users.objects.get(Q(username=username) | Q(mobile=username))
        except Exception as e:
            print(e)
            return Response({"msg": "用户不存在", "code": 400})
        # 数据库中的密码是密文存储的,前端传来的是明文 ,两个是不一样的,加密不可逆
        # check_password(没有加密的密码,加密的密码)
        if check_password(pwd, user.password):
            # 生成token,并返回
            # 传入第二部分的用户信息
            payload = jwt_payload_handler(user)
            # 根据第二部分生成token
            token = jwt_encode_handler(payload)
            # cookie是在响应中生成的
            resp = Response({"msg": "欢迎%s" % username, 'user': {"userName": user.username, 'uid': user.id}, "code": 200,
                             "token": token})
            resp.set_cookie("token", token)
            return resp

            # # 密码正确
            # request.session["username"] = username
            # return Response(
            #     {"msg": "欢迎%s" % username, 'user': {"userName": user.username, 'uid': user.id}, "code": 200,
            #      "token": token})
        # 验证未通过
        return Response({"msg": "用户名或密码不正确", "code": 400})

    # def post(self, request):
    #     username = request.data.get("user")
    #     pwd = request.data.get("pwd")
    #     # 校验
    #     # 使用
    #     user = authenticate(username=username, password=pwd)
    #     if user:
    #         # 生成token,并返回
    #         # 传入第二部分的用户信息
    #         payload = jwt_payload_handler(user)
    #         # 根据第二部分生成token
    #         token = jwt_encode_handler(payload)
    #         request.session["username"] = username
    #
    #         return Response(
    #             {"msg": "欢迎%s" % username, 'user': {"userName": user.username, 'uid': user.id}, "code": 200,
    #              "token": token})
    #     # 验证未通过
    #     return Response({"msg": "用户名或密码不正确", "code": 400})


# 退出登录
class Logout(APIView):
    def post(self, request):
        # # 删除cookie
        # token = request.COOKIES.get("token")
        # if token:
        #     del token

        # 删除session
        if request.session.get("username"):
            del request.session["username"]

        return Response({"mag": "OK", "code": 200})


# 查询用户信息
class GetUserInfo(APIView):
    def post(self, request):
        user = request.data.get("user")
        print("user>>>>>", user)
        try:
            # 查询用户信息
            user_ = Users.objects.get(username=user["userName"])
        except Exception as e:
            print(e)
            return Response({"msg": "请先登录", "code": 400})
        # 通过用户对象  反向查询 得到所有的收货地址
        data = user_.address_set.all()
        # 进行序列化
        addr_ser = AddressSer(data, many=True)
        # 返回用户名   手机号  收货地址  code  msg   // 根据前端来写
        return Response(
            {"code": 200,
             "msg": "获取用户信息成功",
             "userInfo": {"username": user_.username, "mobile": user_.mobile, "addrs": addr_ser.data}})


# 添加收货地址
class AddAddressView(APIView):
    def post(self, request):
        # 获取前端传来的信息
        user = request.data.get("user")
        receiver = request.data.get("receiver")
        receive_mobile = request.data.get("receive_mobile")
        receive_addr = request.data.get("receive_addr")
        is_default = request.data.get("is_default")
        print("user>>>>>", user)
        try:
            # 查询用户信息
            user_ = Users.objects.get(username=user["userName"])
        except Exception as e:
            print(e)
            return Response({"msg": "请先登录", "code": 400})
        if not all([receive_addr, receive_mobile, receiver]):
            return Response({"msg": "请完善收货信息", 'code': 400})
        try:
            addr = Address.objects.create(receiver=receiver,
                                          receive_mobile=receive_mobile,
                                          receive_addr=receive_addr,
                                          is_default=is_default, user_id=user_.id)
        except Exception as e:
            print(e)
            return Response({"msg": "添加失败", "code": 400})
        add_ser = AddressSer(addr)
        return Response({"addr": add_ser.data, "code": 200, 'msg': "添加成功"})


# 修改个人信息
class UpdateUserInfo(APIView):
    def post(self, request):
        """
        user: this.$store.getters.getUser,
        phone: this.userInfo.mobile,
        addrs: this.userInfo.addrs
        """
        user = request.data.get("user")
        mobile = request.data.get("mobile")
        addrs = request.data.get("addrs")  # 收货地址传过来的是个 字典列表
        print("修改个人信息user>>>>>>>", user)
        print("收货地址addrs>>>>>>>>", addrs)
        print(mobile)
        # 接收数据是否为空
        if not all([mobile, addrs]):
            return Response({"msg": "请完善信息", "code": 400})
        # 判断用户是否登录
        try:
            user_ = Users.objects.get(username=user["userName"])
        except Exception as e:
            print(e)
            return Response({"msg": "请先登录", 'code': 400})
        # 校验手机号是否需要修改
        if user_.mobile != mobile:
            if Users.objects.filter(mobile=mobile).count() > 0:  # 判断手机号是否存在于用户表  大于0  报手机号已存在
                return Response({"msg": "手机号已存在,请更换手机号!"})
            # 否则就修改用户手机号
            user_.mobile = mobile
            user_.save()  # 保存
        # 循环收货地址   通过filter查询id   update进行修改
        for i in addrs:
            Address.objects.filter(id=i["id"]).update(receiver=i["receiver"],
                                                      receive_mobile=i["receive_mobile"],
                                                      receive_addr=i["receive_addr"])
        return Response({"msg": "用户信息更新成功", 'code': 200})


# 删除收货地址
class DelAddressInfo(APIView):
    def post(self, request):
        addr_id = request.data.get("addr_id")
        try:
            Address.objects.get(id=addr_id).delete()
        except Exception as e:
            print(e)
            return Response({"msg": "地址不存在"})
        return Response({"msg": "删除成功", 'code': 200})


# 修改密码
class UpdatePwdView(APIView):
    def post(self, request):
        # user 用户名
        # originPw  原密码
        # newPw  新密码
        # confirmNewPw  确认密码
        username = request.data.get("user")
        originPw = request.data.get("originPw")
        newPw = request.data.get("newPw")
        confirmNewPw = request.data.get("confirmNewPw")
        print("修改密码信息>>>>>>>", username, originPw, newPw, confirmNewPw)
        if originPw == newPw:
            return Response({"msg": "新旧密码相同,请重新输入!!"})
        if newPw != confirmNewPw:
            return Response({"msg": "两次输入的密码不同,请重新输入!!!"})
        try:
            # 获取用户信息
            user = Users.objects.get(username=username)
        except Exception as e:
            print(e)
            return Response({"msg": "用户不存在,请重新输入!!!"})
        # 没加密的   加密的
        if not check_password(originPw, user.password):
            return Response({"msg": "原密码错误", "code": 400})
        user.password = make_password(newPw)  # make_password()  用于对密码加密
        user.save()
        return Response({"msg": "修改成功", "code": 200})
